<%@page import="org.apache.http.HttpEntity"%>
<%@page import="org.apache.http.impl.client.DefaultHttpClient"%>
<%@page import="org.apache.http.util.EntityUtils"%>
<%@page import="org.apache.http.client.HttpClient"%>
<%@page import="org.apache.http.HttpResponse"%>
<%@page import="org.apache.http.client.methods.HttpGet"%>
<%@page import="org.apache.http.client.utils.URIUtils"%>
<%@page import="java.net.URI"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.text.DateFormat"%>
<%@page import="java.util.Date"%>
<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@page import="java.util.ArrayList"%>
<%@page import="org.apache.commons.collections.ListUtils"%>
<%@page import="com.gilstar.util.Utils"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>

<%@page import="java.util.List"%>
<%@page import="org.apache.commons.lang.ArrayUtils"%>
<%@page import="org.apache.commons.lang.StringUtils"%>
<%@page import="org.json.JSONObject"%>
<%@page import="com.gilstar.common.Constant"%>
<%@page import="org.apache.commons.codec.binary.Hex"%>
<%@page import="codeartist.ibatis.SQLManager"%>
<%@page import="codeartist.json.JSONHandler"%>
<%@page import="org.slf4j.LoggerFactory"%>
<%@page import="org.slf4j.Logger"%>

<%!
	private static Logger log = LoggerFactory.getLogger("Performance.jsp");
	private static DateFormat yyyyMMddFromat = new SimpleDateFormat("yyyy-MM-dd");

	private JSONHandler jsonHandler;
	private SQLManager sqlManager = SQLManager.getInstance();
	
	private ServletContext scx;
	private Hex h;
	
	private List getPerformanceList(String keyword, int page_no) throws Exception
	{
		Map param = new HashMap();
		param.put(Constant.KEYWORD, keyword);
		param.put(Constant.PAGE_NO, page_no);
		param.put(Constant.PAGE_ROW_COUNT, Constant.PAGE_ROW_COUNT_VALUE);
		
		log.debug("search keyword : {}", keyword);
		log.debug("current page : {}", page_no);
		
		List rList = sqlManager.select(Constant.SQLMAP_SELECT_PERFORMANCE_LIST, param);
		
		log.debug("result List : {}", rList);
		
		if(rList.size() == Integer.valueOf(0))
		{
			rList = ListUtils.EMPTY_LIST;
		}
		
		return rList;
	}
	
	private List getPerformanceListFromMap(Map param) throws Exception
	{
		if(param.size() == Integer.valueOf(0))
		{
			return ListUtils.EMPTY_LIST;
		}
		else
		{
			return sqlManager.select(Constant.SQLMAP_SELECT_PERFORMANCE_FROM_MAP, param);
		}
	}
	
	private List getPerformanceListFromList(Map param) throws Exception
	{
		if(param.size() == Integer.valueOf(0))
		{
			return ListUtils.EMPTY_LIST;
		}
		else
		{
			return sqlManager.select(Constant.SQLMAP_SELECT_PERFORMANCE_FROM_LIST, param);
		}
	}
	
	private List getCommentList(int performanseSeq) throws Exception
	{
		Map param = new HashMap();
		param.put(Constant.PERFORMANCE_SEQ, performanseSeq);
		List rList = sqlManager.select(Constant.SQLMAP_SELECT_COMMENT);
		if(rList.size() == Integer.valueOf(0))
		{
			rList = ListUtils.EMPTY_LIST;
		}
		return rList;
	}

%>

<%
	h = new Hex();
	jsonHandler = new JSONHandler();
	
	try
	{
		JSONObject req = jsonHandler.read(request);
		
		log.debug("req : [" + req + "]");
		
		String mname = req.getString(Constant.REQ);
		if(StringUtils.equals(mname, "test"))
		{
			List rList = sqlManager.select("Performance.test");
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, ArrayUtils.toString(rList));
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_REGISTER_PERFORMANCE))
		{
			String title = Utils.convertJSON(new String((byte[])(h.decode(req.optString(Constant.TITLE, Constant.EMPTY))), Constant.CV_UTF8));
			log.debug("title : {}", title);
			String artist = Utils.convertJSON(new String((byte[])(h.decode(req.optString(Constant.ARTIST, Constant.EMPTY))), Constant.CV_UTF8));
			log.debug("artist : {}", artist);
			String category = req.optString(Constant.CATEGORY, Constant.EMPTY);
			log.debug("category : {}", category);
			double latitude = Double.parseDouble(req.optString(Constant.LATITUDE, "0"));
			log.debug("latitude : {}", latitude);
			double longitude = Double.parseDouble(req.optString(Constant.LONGITUDE, "0"));
			log.debug("longitude : {}", longitude);
			String date = req.getString(Constant.DATE);
			log.debug("date : {}", date);
			String time = req.getString(Constant.TIME);
			log.debug("time : {}", time);
			String content = Utils.convertJSON(new String((byte[])(h.decode(req.optString(Constant.CONTENT, Constant.EMPTY))), Constant.CV_UTF8));
			log.debug("content : {}", content);
			String email = req.getString(Constant.EMAIL);
			log.debug("email : {}", email);
			String sns_url = req.optString(Constant.SNS_URL);
			log.debug("sns_url : {}", sns_url);
			String youtube_link = req.optString(Constant.YOUTUBE_LINK);
			log.debug("youtube link : {}", youtube_link);
			
			String address = Utils.convertJSON(new String((byte[])(h.decode(req.optString(Constant.ADDRESS, Constant.EMPTY))), Constant.CV_UTF8));
			log.debug("address : {}", address);
			if(StringUtils.isBlank(title) || StringUtils.length(title) > 100)
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.TITLE_INVAILIDE_MESSAGE, null);
				return;
			}
			
			if(latitude == Double.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LATITUDE_INVALIDE_MESSAGE, null);
				return;
			}
			
			if(longitude == Double.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LONGITUDE_INVALIDE_MESSAGE, null);
				return;
			}
			
			if(StringUtils.length(email) > 50)
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LOGIN_REQUIRED_SERVICE, null);
				return;
			}
			
			if(StringUtils.isBlank(category))
			{
				category = "others";
			}
			
			if(StringUtils.isBlank(date) || StringUtils.isBlank(time))
			{
				time = Utils.getToday();
			}
			else
			{
				time = date + " " + time;
			}
			
			Map param = new HashMap();
			param.put(Constant.EMAIL, email);
			
			param.put(Constant.TITLE, title);
			param.put(Constant.ARTIST, artist);
			param.put(Constant.CATEGORY, category);
			param.put(Constant.LATITUDE, latitude);
			param.put(Constant.LONGITUDE, longitude);
			param.put(Constant.TIME, time);
			param.put(Constant.CONTENT, content);
			param.put(Constant.SNS_URL, sns_url);
			
			param.put(Constant.YOUTUBE_LINK, youtube_link);
			param.put(Constant.ADDRESS, address);
			
			int currentKey = 0;
			
			try
			{
				sqlManager.startTransaction();
				currentKey = sqlManager.insert(Constant.SQLMAP_INSERT_PERFORMANCE, param);
				log.debug("current key : {}", currentKey);
				
				if(currentKey != Integer.valueOf(0))
				{
					sqlManager.commitTransaction();
				}
			}
			catch(Exception e)
			{
				throw new RuntimeException(e.getMessage());
			}
			finally
			{
				sqlManager.endTransaction();
			}
			
			Map rMap = new HashMap();
			rMap.put(Constant.PERFORMANCE_SEQ, currentKey);
			List rList = new ArrayList();
			rList.add(rMap);
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.INSERT_OK, rList);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_PERFORMANCE_FROM_MAP))
		{
			double latitude = Double.parseDouble(req.optString(Constant.LATITUDE, "0")); 
			double longitude = Double.parseDouble(req.optString(Constant.LONGITUDE, "0"));
			
			if( latitude == Double.valueOf(0) && longitude == Double.valueOf(0) )
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LOCATION_INVALID_MESSAGE, null);
				return;
			}

			//int amount - req.
			int dayAdd = Integer.parseInt(req.getString(Constant.DAY_ADD));
			long datetime = new Date().getTime();
			datetime += 24*60*60*1000 * dayAdd;
			String dateString = yyyyMMddFromat.format(new Date(datetime));
			
			Map<String, Object> param = new HashMap<String, Object>();
			param.put(Constant.MAX_TIME, dateString + " 23:59:59");
			param.put(Constant.MIN_TIME, dateString + " 00:00:00");
			
			param.put(Constant.LATITUDE, latitude);
			param.put(Constant.LONGITUDE, longitude);
			
			for (String key : param.keySet()) 
			{
				log.debug(key + " : {}", param.get(key));
			}
			
			List rList = getPerformanceListFromMap(param);
			
			log.debug("result list : {}", rList);
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, rList);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_PERFORMANCE_FROM_LIST))
		{
			double latitude = Double.parseDouble(req.optString(Constant.LATITUDE, "0"));
			double longitude = Double.parseDouble(req.optString(Constant.LONGITUDE, "0"));
			log.debug("latitude : {}", latitude);
			log.debug("longitude : {}", longitude);

			double maxLatitude = latitude + 0.02;
			double maxLongitude = longitude + 0.02;
			double minLatitude = latitude - 0.02;
			double minLongitude = longitude - 0.02;
			
			if((maxLatitude == Double.valueOf(0) && maxLongitude == Double.valueOf(0)) 
					|| (minLatitude == Double.valueOf(0) && minLongitude == Double.valueOf(0)))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LOCATION_INVALID_MESSAGE, null);
				return;
			}

			//int amount - req.
			int dayAdd = Integer.parseInt(req.getString(Constant.DAY_ADD));
			int time = Integer.parseInt(req.getString(Constant.TIME));
			long datetime = new Date().getTime();
			datetime += 24*60*60*1000 * dayAdd;
			String dateString = yyyyMMddFromat.format(new Date(datetime));
			String minTime = dateString + " ";
			if (time < 10) {
			    minTime += "0";
			}
		    minTime += time + ":00:00";
			String maxTime = dateString + " ";
			if ((time + 1) < 10) {
			    maxTime += "0";
			}
		    maxTime += (time+1) + ":59:59";
			
			log.debug("max liatitude : {}, max longitude : {}", maxLatitude, maxLongitude);
			log.debug("min liatitude : {}, min longitude : {}", minLatitude, minLongitude);
			
			Map<String, Object> param = new HashMap<String, Object>();
			param.put(Constant.MAX_TIME, maxTime);
			param.put(Constant.MIN_TIME, minTime);
			param.put(Constant.MAX_LATITUDE, maxLatitude);
			param.put(Constant.MAX_LONGITUDE, maxLongitude);
			param.put(Constant.MIN_LATITUDE, minLatitude);
			param.put(Constant.MIN_LONGITUDE, minLongitude);
			for (String key : param.keySet()) {
				log.debug(key + " : {}", param.get(key));
			}
			
			List rList = getPerformanceListFromList(param);
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, rList);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_PERFORMANCE_DETAIL))
		{
			int performance_seq = Integer.parseInt(req.optString(Constant.PERFORMANCE_SEQ, "0"));
			log.debug("performance seq : {}", performance_seq);
			Map param = new HashMap();
			param.put(Constant.PERFORMANCE_SEQ, performance_seq);
			
			List rList = sqlManager.select(Constant.SQLMAP_SELECT_PERFORMANCE_DETAIL, param);
			if(rList.size() == Integer.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.PERFORMANCE_SEQ_INVALID_MESSAGE, ListUtils.EMPTY_LIST);
				return;
			}
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, rList);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_PERFORMANCE_LIST))
		{
			String keyword = Utils.convertJSON(new String((byte[])(h.decode(req.optString(Constant.KEYWORD, Constant.EMPTY))), Constant.CV_UTF8));
			int page_no = Integer.parseInt(req.optString(Constant.PAGE_NO, "1"));
			
			if(page_no < 0)
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.INVALID_PAGE_NUMBER_MESSAGE, null);
			}
			
			//condition exist?? or all condition search??
			
			List rList = getPerformanceList(keyword, page_no);
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, rList);
			
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_ADD_COMMENT))
		{
			int performanceSeq = Integer.parseInt(req.optString(Constant.PERFORMANCE_SEQ, "0"));
			String comment = Utils.convertJSON(new String((byte[])(h.decode(req.optString(Constant.COMMENT_CONTENT, Constant.EMPTY))), Constant.CV_UTF8));
			String email = req.getString(Constant.EMAIL);
			
			log.debug("performance seq : {}", performanceSeq);
			log.debug("comment : {}", comment);
			log.debug("email : {}", email);
			
			if(performanceSeq == Integer.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.PERFORMANCE_SEQ_INVALID_MESSAGE, ListUtils.EMPTY_LIST);
				return;
			}
			
			if(StringUtils.isBlank(email) || StringUtils.length(email) > 50)
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LOGIN_REQUIRED_SERVICE, null);
				return;
			}
			
			Map param = new HashMap();
			param.put(Constant.PERFORMANCE_SEQ, performanceSeq);
			param.put(Constant.COMMENT_CONTENT, comment);
			param.put(Constant.EMAIL, email);
			
			try
			{
				sqlManager.startTransaction();
				int count = sqlManager.update(Constant.SQLMAP_INSERT_COMMENT, param);
				if(count == Integer.valueOf(0))
				{
					sqlManager.commitTransaction();
				}
				else
				{
					throw new RuntimeException("comment not registered."); 
				}
			}
			catch(Exception e)
			{
				log.error("exception : {}", e.getMessage());
				throw e;
			}
			finally
			{
				sqlManager.endTransaction();
			}
			
			List rList = this.getCommentList((Integer)param.get(Constant.PERFORMANCE_SEQ));
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_COMMENT_LIST))
		{
			int performanceSeq = Integer.parseInt(req.optString(Constant.PERFORMANCE_SEQ, "0"));
			
			log.debug("performance seq : {}", performanceSeq);
			
			if(performanceSeq == Integer.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.PERFORMANCE_SEQ_INVALID_MESSAGE, ListUtils.EMPTY_LIST);
				return;
			}
			List rList = this.getCommentList(performanceSeq);
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, rList);	
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_NEAREST_HOTSPOT))
		{
			double latitude = Double.parseDouble(req.optString(Constant.LATITUDE, "0"));
			log.debug("latitude : {}", latitude);
			double longitude = Double.parseDouble(req.optString(Constant.LONGITUDE, "0"));
			log.debug("longitude : {}", longitude);
			
			if(latitude == Double.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LATITUDE_INVALIDE_MESSAGE, null);
				return;
			}
			
			if(longitude == Double.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.LONGITUDE_INVALIDE_MESSAGE, null);
				return;
			}
			
			List nList = sqlManager.select(Constant.SQLMAP_SELECT_ALL_HOTSPOT);
			if(nList.size() == 0)
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.ANY_HOT_SPOT_REGISTERED, null);
				return;
			}
			
			int nCount = nList.size();
			
			double nearestDistance = 0;
			
			int nearestHotspotSeq = 0;
			
			for(int i = 0; i < nCount; i++)
			{
				int targetLatitude = (Integer)((HashMap)nList.get(i)).get(Constant.LATITUDE);
				int targetLongitude = (Integer)((HashMap)nList.get(i)).get(Constant.LONGITUDE);
				int targetHotSpotSeq = (Integer)((HashMap)nList.get(i)).get(Constant.HOT_SPOT_SEQ);
				double distance = Utils.distance(latitude, longitude, targetLatitude, targetLongitude);
				
				if(nearestDistance == 0)		//not initialized
				{
					nearestDistance = distance;
					nearestHotspotSeq = targetHotSpotSeq;
				}
				else				//after initailzed
				{
					if(distance < nearestDistance)
					{
						distance = nearestDistance;
						nearestHotspotSeq = targetHotSpotSeq;
					}
				}
			}
			
			Map param = new HashMap();
			param.put(Constant.HOT_SPOT_SEQ, nearestHotspotSeq);
			
			List rList = sqlManager.select(Constant.SQLMAP_SELECT_HOT_SPOT, param);
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, rList);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_HOTSPOT_LIST))
		{
			List nList = sqlManager.select(Constant.SQLMAP_SELECT_ALL_HOTSPOT);
			if(nList.size() == 0)
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.ANY_HOT_SPOT_REGISTERED, null);
				return;
			}
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, nList);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_RANDOM_PERFORMANCE))
		{
			List rList = sqlManager.select(Constant.SQLMAP_SELECT_RANDOM_PERFORMANCE);
			if(rList.size() == Integer.valueOf(0))
			{
				rList = ListUtils.EMPTY_LIST;
			}
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, rList);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_GET_ADDRESS))
		{

			//get address info
			double latitude = Double.parseDouble(req.optString(Constant.LATITUDE, "0"));
			log.debug("latitude : {}", latitude);
			double longitude = Double.parseDouble(req.optString(Constant.LONGITUDE, "0"));
			log.debug("longitude : {}", longitude);
			
			
			URI uri = URIUtils.createURI("http", "maps.google.com/maps/api/geocode", -1, "/json", "latlng=" + latitude + "," + longitude + "&sensor=false&language=ko", null);
			
			log.debug("uri : {}", uri);
			
			HttpGet httpget = new HttpGet(uri);
			
			log.debug("header info : {}", httpget.getAllHeaders());
			HttpClient client = new DefaultHttpClient();
			HttpResponse addressResponse = client.execute(httpget);
			log.debug("google address response code : {}", addressResponse.getStatusLine().getStatusCode());
			HttpEntity entity = addressResponse.getEntity();
			String result = EntityUtils.toString(entity);
			
			JSONObject object = new JSONObject(result);
			
			log.debug("result object : {}", object);
			
			String address = StringUtils.trim(((JSONObject)(object.getJSONArray("results")).get(0)).getString("formatted_address"));
			log.debug("address : {}", address);
			
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.EMPTY, address);
		}
		else if(StringUtils.equals(mname, Constant.METHOD_NAME_DELETE_PERFORMANCE))
		{
			int performanceSeq = Integer.parseInt(req.optString(Constant.PERFORMANCE_SEQ, "0"));
			
			log.debug("performance seq : {}", performanceSeq);
			
			if(performanceSeq == Integer.valueOf(0))
			{
				jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.PERFORMANCE_SEQ_INVALID_MESSAGE, ListUtils.EMPTY_LIST);
				return;
			}
			
			Map param = new HashMap();
			param.put(Constant.PERFORMANCE_SEQ, performanceSeq);
			try
			{
				sqlManager.startTransaction();
				
				int deleteCount = sqlManager.delete(Constant.SQLMAP_DELETE_PERFORMANCE, param);
				if(deleteCount == Integer.valueOf(0))
				{
					sqlManager.commitTransaction();
				}
			}
			catch(Exception e)
			{
				throw e;
			}
			finally
			{
				sqlManager.endTransaction();
			}
			jsonHandler.flush(response, JSONHandler.SERVER_EXECUTION_CODE, Constant.INSERT_OK, null);
		}
		
	}
	catch(Exception e)
	{
		log.error("Performance.jsp exception : {}", e.getMessage());
		jsonHandler.flush(response, JSONHandler.SERVER_ERROR_CODE, Constant.ERROR_MESSAGE, null);
	}
%>